/**
*  \file pal_mem.h
*
*  \brief Platform optimized memory functions.
*
*  \author Michael J. Hohmann  michael.hohmann@linde-mh.de
*
*/
#ifndef PAL_MEM_H_INCLUDED
#define PAL_MEM_H_INCLUDED

/*================================================[ public includes  ]================================================*/
#include "../cfg/prj.h"
#include "../assertor/assertor.h"


/*================================================[ public defines   ]================================================*/

/*================================================[ public datatypes ]================================================*/

/*================================================[ public variables ]================================================*/

/*================================================[ inline functions ]================================================*/

/** Set memory to zero
*	The function pal_memzero fill count bytes
*	This is a substitute for the posix function bzero().
*
*/
STATIC_INLINE void pal_memzero( void *dest, pal_size_t count )
{
	ASSERTOR_PRE( NIL != dest, "dest pointer must not be NIL");
	U8 *p=(U8*)dest;

	while(count--)
	{
	   *p=0;
	   p++;
	}
}

/** Memory set function
*
* 	The pal_memset function copies the parameter value into each of the first count characters of the object pointed to by dest.
* 	The function pal_memset is intended as a substitute for the library function memset().
* 	Differently to the original library function this function does not have a return value.
*
* 	\param dest Pointer to the destination.
* 	\param value Value to fill the destination.
*	\param count Number of byte to fill.
*
*/
STATIC_INLINE void pal_memset( void *dest, U8 value, pal_size_t count )
{
	ASSERTOR_PRE( NIL != dest, "dest pointer must not be NIL");
   U8 *p=(U8*)dest;

   while(count--)
   {
      *p=value;
      p++;
   }
}



/** Memory Compare
*
* 	The pal_memcmp function compares the first n characters of the object pointed to by s1 to
*	the first n characters of the object pointed to by s2.
*
* 	\return The memcmp function returns a signed value greater than, equal to, or less than zero,
*			accordingly as the object pointed to by s1 is greater than, equal to, or less than the object
*			pointed to by s2
*/
STATIC_INLINE S8 pal_memcmp(const void *s1, const void *s2, pal_size_t count)
{
	ASSERTOR_PRE( NIL != s1, "s1 pointer must not be NIL");
	ASSERTOR_PRE( NIL != s2, "s2 pointer must not be NIL");

	U8 *p1=(U8*)s1;
   U8 *p2=(U8*)s2;

   while(count--)
   {
      if(*p1!=*p2)
      {
         if(*p1>*p2)
         {
            return 1;
         }
         else
         {
            return -1;
         }
      }
      p1++;
      p2++;
   }

	return 0;

}

/**	Copy memory
* 	The memcpy function copies n characters from the object pointed to by s2 into the
* 	object pointed to by s1.
* 	If copying takes place between objects that overlap, the behavior is undefined.
*
* 	\param dest Pointer to the destination.
* 	\param src  Pointer to the source.
* 	\param count Number of bytes to copy
*
*/

STATIC_INLINE void pal_memcpy( RESTRICT void *dest, RESTRICT void const*src, pal_size_t count )
{
	ASSERTOR_PRE( NIL != dest,"dest pointer must not be NIL");
	ASSERTOR_PRE( NIL != src, "src pointer must not be NIL");
	ASSERTOR_PRE( dest!=src,  "src and dest can't be same (RESTRICT)");
   U8 *d=(U8*)dest;
   U8 *s=(U8*)src;

   while(count--)
   {
      *d=*s;
      s++;
      d++;
   }
}
/** Copy two bytes in reverse order.
*
* 	\param dest Pointer to the destination.
* 	\param src  Pointer to the source.
*/

STATIC_INLINE void pal_memcpy_reverse( RESTRICT void *dest, RESTRICT void const*src, pal_size_t count )
{
	ASSERTOR_PRE( NIL != dest,"dest pointer must not be NIL");
	ASSERTOR_PRE( NIL != src, "src pointer must not be NIL");
	ASSERTOR_PRE( dest!=src,  "src and dest can't be same (RESTRICT)");
   U8 *d=((U8*)dest) + count - 1;
   U8 *s=(U8*)src;

   while(count--)
   {
      *d=*s;
      s++;
      d--;
   }
}

/** Copy two bytes.
*
* 	\param dest Pointer to the destination.
* 	\param scr  Pointer to the source.
*/
STATIC_INLINE void pal_memcpy_2( RESTRICT void *dest, RESTRICT void const*src )
{
	ASSERTOR_PRE( NIL != dest,"dest pointer must not be NIL");
	ASSERTOR_PRE( NIL != src, "src pointer must not be NIL");
	ASSERTOR_PRE( dest!= src, "src and dest can't be same (RESTRICT)");
	{
		U8 *d=(U8*)dest;
		U8 const *s=(U8*)src;
		*d++=*s++;
		*d=*s;
	}
}

/** Copy two bytes in reverse order.
*
* 	\param dest Pointer to the destination.
* 	\param src  Pointer to the source.
*/
STATIC_INLINE void pal_memcpy_reverse_2( RESTRICT void *dest, RESTRICT void const*src )
{
	ASSERTOR_PRE( NIL != dest,"dest pointer must not be NIL");
	ASSERTOR_PRE( NIL != src, "src pointer must not be NIL");
	ASSERTOR_PRE( dest!= src, "src and dest can't be same (RESTRICT)");
	{
		U8 *d=((U8*)dest)+1;
		U8 const *s=(U8*)src;
		*d--=*s++;
		*d=*s;
	}
}

/** Copy four bytes.
*
* 	\param dest Pointer to the destination.
* 	\param scr  Pointer to the source.
*/
STATIC_INLINE void pal_memcpy_4( RESTRICT void *dest, RESTRICT void const*src )
{
	ASSERTOR_PRE( NIL != dest,"dest pointer must not be NIL");
	ASSERTOR_PRE( NIL != src, "src pointer must not be NIL");
	ASSERTOR_PRE( dest!= src, "src and dest can't be same (RESTRICT)");
	{
		U8 *d=(U8*)dest;
		U8 const *s=(U8*)src;
		*d++=*s++;
		*d++=*s++;
		*d++=*s++;
		*d=*s;
	}
}

/** Copy four bytes in reverse order.
*
* 	\param dest Pointer to the destination.
* 	\param src  Pointer to the source.
*/
STATIC_INLINE void pal_memcpy_reverse_4( RESTRICT void *dest, RESTRICT void const*src )
{
	ASSERTOR_PRE( NIL != dest,"dest pointer must not be NIL");
	ASSERTOR_PRE( NIL != src, "src pointer must not be NIL");
	ASSERTOR_PRE( dest!= src, "src and dest can't be same (RESTRICT)");
	{
		U8 *d=((U8*)dest)+3;
		U8 const *s=(U8*)src;
		*d--=*s++;
		*d--=*s++;
		*d--=*s++;
		*d=*s;
	}
}

/** Copy eight bytes.
*
* 	\param dest Pointer to the destination.
* 	\param scr  Pointer to the source.
*/
STATIC_INLINE void pal_memcpy_8( RESTRICT void *dest, RESTRICT void const*src )
{
	ASSERTOR_PRE( NIL != dest,"dest pointer must not be NIL");
	ASSERTOR_PRE( NIL != src, "src pointer must not be NIL");
	ASSERTOR_PRE( dest!= src, "src and dest can't be same (RESTRICT)");
	{
		U8 *d=(U8*)dest;
		U8 const *s=(U8*)src;
		*d++=*s++;
		*d++=*s++;
		*d++=*s++;
		*d++=*s++;
		*d++=*s++;
		*d++=*s++;
		*d++=*s++;
		*d=*s;
	}
}

/** Copy eight bytes in reverse order.
*
* 	\param dest Pointer to the destination.
* 	\param src  Pointer to the source.
*/
STATIC_INLINE void pal_memcpy_reverse_8( RESTRICT void *dest, RESTRICT void const*src )
{
	ASSERTOR_PRE( NIL != dest,"dest pointer must not be NIL");
	ASSERTOR_PRE( NIL != src, "src pointer must not be NIL");
	ASSERTOR_PRE( dest!= src, "src and dest can't be same (RESTRICT)");
	{
		U8 *d=((U8*)dest)+7;
		U8 const *s=(U8*)src;
		*d--=*s++;
		*d--=*s++;
		*d--=*s++;
		*d--=*s++;
		*d--=*s++;
		*d--=*s++;
		*d--=*s++;
		*d=*s;
	}
}
/*================================================[ public functions ]================================================*/

/*====================================================================================================================*/

#endif

/***********************************************************************************************************************
*                             Copyright 2018 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
